package tasks.io.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tasks.io.core.ReadCompletionHandler;
import tasks.io.core.SystemTimer;

import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;


public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {

    private static final Logger log = LoggerFactory.getLogger(AcceptCompletionHandler.class);

    public AcceptCompletionHandler() {
    }

    @Override
    public void completed(AsynchronousSocketChannel asynchronousSocketChannel, Server server) {
        try {
            TioServerConfig tioServerConfig = server.getTioServerConfig();
            InetSocketAddress inetSocketAddress = (InetSocketAddress) asynchronousSocketChannel.getRemoteAddress();
            String clientIp = inetSocketAddress.getHostString();


            if (1 == 0) {
                log.info("{}在黑名单中, {}", clientIp, tioServerConfig.getName());
                asynchronousSocketChannel.close();
                return;
            }

            if (tioServerConfig.statOn) {
                ((ServerGroupStat) tioServerConfig.groupStat).accepted.incrementAndGet();
            }


            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 64 * 1024);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 64 * 1024);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);

            ServerChannelContext serverChannelContext = new ServerChannelContext(tioServerConfig, asynchronousSocketChannel);
            serverChannelContext.setClosed(false);
            serverChannelContext.channelStat.setTimeFirstConnected(SystemTimer.currTime);
            serverChannelContext.setServerNode(server.getServerNode());

            //			channelContext.traceClient(ChannelAction.CONNECT, null, null);

            //tioServerConfig.connecteds.add(channelContext);


            boolean isConnected = true;
            boolean isReconnect = false;
            if (tioServerConfig.getTioServerListener() != null) {

                {
                    try {
                        tioServerConfig.getTioServerListener().onAfterConnected(serverChannelContext, isConnected, isReconnect);
                    } catch (Throwable e) {
                        log.error(e.toString(), e);
                    }
                }
            }


            if (!server.isWaitingStop()) {
                ReadCompletionHandler readCompletionHandler = serverChannelContext.getReadCompletionHandler();
                ByteBuffer readByteBuffer = readCompletionHandler.getReadByteBuffer();//ByteBuffer.allocateDirect(channelContext.tioConfig.getReadBufferSize());
                readByteBuffer.position(0);
                readByteBuffer.limit(readByteBuffer.capacity());
                asynchronousSocketChannel.read(readByteBuffer, readByteBuffer, readCompletionHandler);
            }
        } catch (Throwable e) {
            log.error("", e);
        } finally {
            if (server.isWaitingStop()) {
                log.info("{}即将关闭服务器，不再接受新请求", server.getServerNode());
            } else {
                AsynchronousServerSocketChannel serverSocketChannel = server.getAsynchronousServerSocketChannel();
                serverSocketChannel.accept(server, this);
            }
        }
    }


    @Override
    public void failed(Throwable exc, Server server) {
        AsynchronousServerSocketChannel asynchronousServerSocketChannel = server.getAsynchronousServerSocketChannel();
        asynchronousServerSocketChannel.accept(server, this);

        log.error("[" + server.getServerNode() + "]监听出现异常", exc);

    }

}
